using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;

namespace BanZuiCloudControlAgent.Utils.Common
{
    /// <summary>
    /// Win32 API 封装类，提供对常用Windows API的访问
    /// </summary>
    public static class Win32Api
    {
        #region 窗口查找与操作

        /// <summary>
        /// 根据类名和窗口标题查找窗口句柄
        /// </summary>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);

        /// <summary>
        /// 获取窗口标题文本
        /// </summary>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);

        /// <summary>
        /// 枚举所有顶级窗口
        /// </summary>
        [DllImport("user32.dll")]
        public static extern bool EnumWindows(EnumWindowsProc enumProc, IntPtr lParam);

        /// <summary>
        /// 枚举窗口回调委托
        /// </summary>
        public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);

        /// <summary>
        /// 获取窗口类名
        /// </summary>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetClassName(
            IntPtr hWnd,
            StringBuilder lpClassName,
            int nMaxCount
        );

        /// <summary>
        /// 判断窗口是否可见
        /// </summary>
        [DllImport("user32.dll")]
        public static extern bool IsWindowVisible(IntPtr hWnd);

        /// <summary>
        /// 获取相关窗口句柄
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <param name="uCmd">关系标识</param>
        /// <returns>相关窗口句柄</returns>
        [DllImport("user32.dll")]
        public static extern IntPtr GetWindow(IntPtr hWnd, uint uCmd);

        /// <summary>
        /// 获取指定窗口的线程和进程标识符
        /// </summary>
        /// <param name="hwnd">窗口句柄</param>
        /// <param name="processId">进程ID输出参数</param>
        /// <returns>线程ID</returns>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern int GetWindowThreadProcessId(IntPtr hwnd, out int processId);

        /// <summary>
        /// 激活窗口
        /// </summary>
        [DllImport("user32.dll")]
        public static extern bool SetForegroundWindow(IntPtr hWnd);

        /// <summary>
        /// 显示窗口
        /// </summary>
        [DllImport("user32.dll")]
        public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

        /// <summary>
        /// 发送消息
        /// </summary>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(
            IntPtr hWnd,
            uint Msg,
            IntPtr wParam,
            IntPtr lParam
        );

        /// <summary>
        /// 发送消息（字符串参数）
        /// </summary>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern IntPtr SendMessage(
            IntPtr hWnd,
            uint Msg,
            IntPtr wParam,
            string lParam
        );

        /// <summary>
        /// 投递消息
        /// </summary>
        [DllImport("user32.dll", CharSet = CharSet.Auto)]
        public static extern bool PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);

        /// <summary>
        /// 获取窗口矩形区域
        /// </summary>
        [DllImport("user32.dll")]
        private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);

        /// <summary>
        /// 窗口矩形结构体
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct RECT
        {
            public int Left;
            public int Top;
            public int Right;
            public int Bottom;

            public override string ToString()
            {
                return $"Left: {Left}, Top: {Top}, Right: {Right}, Bottom: {Bottom}, Width: {Right - Left}, Height: {Bottom - Top}";
            }
        }

        #endregion

        #region 窗口关系常量

        /// <summary>
        /// 获取下一个窗口
        /// </summary>
        public const uint GW_HWNDNEXT = 2;

        /// <summary>
        /// 获取前一个窗口
        /// </summary>
        public const uint GW_HWNDPREV = 3;

        /// <summary>
        /// 获取父窗口
        /// </summary>
        public const uint GW_OWNER = 4;

        /// <summary>
        /// 获取子窗口
        /// </summary>
        public const uint GW_CHILD = 5;

        #endregion

        #region 窗口显示状态常量

        /// <summary>
        /// 隐藏窗口
        /// </summary>
        public const int SW_HIDE = 0;

        /// <summary>
        /// 正常显示窗口
        /// </summary>
        public const int SW_NORMAL = 1;

        /// <summary>
        /// 最小化窗口
        /// </summary>
        public const int SW_MINIMIZE = 6;

        /// <summary>
        /// 最大化窗口
        /// </summary>
        public const int SW_MAXIMIZE = 3;

        #endregion

        #region 高级窗口查找方法

        /// <summary>
        /// 根据类名查找所有匹配的窗口
        /// </summary>
        /// <param name="className">窗口类名</param>
        /// <param name="exactMatch">是否精确匹配</param>
        /// <param name="visibleOnly">是否只查找可见窗口，默认为true</param>
        /// <returns>窗口句柄列表</returns>
        public static List<IntPtr> FindWindowsByClassName(
            string className,
            bool exactMatch = true,
            bool visibleOnly = true
        )
        {
            List<IntPtr> result = new List<IntPtr>();

            EnumWindows(
                (hWnd, lParam) =>
                {
                    // 检查窗口可见性
                    if (visibleOnly && !IsWindowVisible(hWnd))
                    {
                        return true; // 如果要求只查找可见窗口，且当前窗口不可见，则跳过
                    }

                    StringBuilder sb = new StringBuilder(256);
                    GetClassName(hWnd, sb, sb.Capacity);
                    string windowClassName = sb.ToString();

                    bool isMatch = exactMatch
                        ? windowClassName == className
                        : windowClassName.Contains(className);

                    if (isMatch)
                    {
                        result.Add(hWnd);
                    }

                    return true;
                },
                IntPtr.Zero
            );

            return result;
        }

        /// <summary>
        /// 根据窗口标题查找所有匹配的窗口
        /// </summary>
        /// <param name="title">窗口标题</param>
        /// <param name="exactMatch">是否精确匹配</param>
        /// <param name="visibleOnly">是否只查找可见窗口，默认为true</param>
        /// <returns>窗口句柄列表</returns>
        public static List<IntPtr> FindWindowsByTitle(
            string title,
            bool exactMatch = true,
            bool visibleOnly = true
        )
        {
            List<IntPtr> result = new List<IntPtr>();

            EnumWindows(
                (hWnd, lParam) =>
                {
                    // 检查窗口可见性
                    if (visibleOnly && !IsWindowVisible(hWnd))
                    {
                        return true; // 如果要求只查找可见窗口，且当前窗口不可见，则跳过
                    }

                    StringBuilder sb = new StringBuilder(256);
                    GetWindowText(hWnd, sb, sb.Capacity);
                    string windowTitle = sb.ToString();

                    bool isMatch = exactMatch ? windowTitle == title : windowTitle.Contains(title);

                    if (isMatch)
                    {
                        result.Add(hWnd);
                    }

                    return true;
                },
                IntPtr.Zero
            );

            return result;
        }

        /// <summary>
        /// 根据进程ID查找其创建的所有窗口
        /// </summary>
        /// <param name="processId">进程ID</param>
        /// <param name="visibleOnly">是否只查找可见窗口，默认为true</param>
        /// <returns>窗口句柄列表</returns>
        public static List<IntPtr> FindWindowsByProcessId(int processId, bool visibleOnly = true)
        {
            List<IntPtr> result = new List<IntPtr>();

            EnumWindows(
                (hWnd, lParam) =>
                {
                    GetWindowThreadProcessId(hWnd, out int windowProcessId);
                    if (windowProcessId == processId)
                    {
                        // 根据visibleOnly参数决定是否只添加可见窗口
                        if (!visibleOnly || IsWindowVisible(hWnd))
                        {
                            result.Add(hWnd);
                        }
                    }
                    return true;
                },
                IntPtr.Zero
            );

            return result;
        }

        /// <summary>
        /// 获取窗口标题
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <returns>窗口标题</returns>
        public static string GetWindowTitle(IntPtr hWnd)
        {
            StringBuilder sb = new StringBuilder(256);
            GetWindowText(hWnd, sb, sb.Capacity);
            return sb.ToString();
        }

        /// <summary>
        /// 获取窗口类名
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <returns>窗口类名</returns>
        public static string GetWindowClassName(IntPtr hWnd)
        {
            StringBuilder sb = new StringBuilder(256);
            GetClassName(hWnd, sb, sb.Capacity);
            return sb.ToString();
        }

        /// <summary>
        /// 获取窗口进程ID
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <returns>进程ID</returns>
        public static int GetWindowProcessId(IntPtr hWnd)
        {
            GetWindowThreadProcessId(hWnd, out int processId);
            return processId;
        }

        /// <summary>
        /// 获取窗口信息
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <returns>包含窗口信息的对象</returns>
        public static WindowInfo GetWindowInfo(IntPtr hWnd)
        {
            WindowInfo info = new WindowInfo
            {
                Handle = hWnd,
                Title = GetWindowTitle(hWnd),
                ClassName = GetWindowClassName(hWnd),
                IsVisible = IsWindowVisible(hWnd),
            };

            GetWindowThreadProcessId(hWnd, out int processId);
            info.ProcessId = processId;

            // 获取窗口位置和大小
            if (GetWindowRectangle(hWnd, out RECT rect))
            {
                info.Left = rect.Left;
                info.Top = rect.Top;
                info.Width = rect.Right - rect.Left;
                info.Height = rect.Bottom - rect.Top;
            }

            return info;
        }

        /// <summary>
        /// 获取窗口的位置和大小
        /// </summary>
        /// <param name="hWnd">窗口句柄</param>
        /// <param name="rect">输出的窗口矩形</param>
        /// <returns>是否成功获取</returns>
        public static bool GetWindowRectangle(IntPtr hWnd, out RECT rect)
        {
            return GetWindowRect(hWnd, out rect);
        }

        #endregion
    }

    /// <summary>
    /// 窗口信息类，存储窗口的基本信息
    /// </summary>
    public class WindowInfo
    {
        /// <summary>
        /// 窗口句柄
        /// </summary>
        public IntPtr Handle { get; set; }

        /// <summary>
        /// 窗口标题
        /// </summary>
        public string Title { get; set; }

        /// <summary>
        /// 窗口类名
        /// </summary>
        public string ClassName { get; set; }

        /// <summary>
        /// 窗口是否可见
        /// </summary>
        public bool IsVisible { get; set; }

        /// <summary>
        /// 窗口所属进程ID
        /// </summary>
        public int ProcessId { get; set; }

        /// <summary>
        /// 窗口左边界坐标
        /// </summary>
        public int Left { get; set; }

        /// <summary>
        /// 窗口上边界坐标
        /// </summary>
        public int Top { get; set; }

        /// <summary>
        /// 窗口宽度
        /// </summary>
        public int Width { get; set; }

        /// <summary>
        /// 窗口高度
        /// </summary>
        public int Height { get; set; }

        /// <summary>
        /// 重写ToString方法，便于输出窗口信息
        /// </summary>
        public override string ToString()
        {
            return $"窗口句柄: 0x{Handle.ToInt64():X}, 标题: {Title}, 类名: {ClassName}, 进程ID: {ProcessId}, 可见: {IsVisible}, 位置: ({Left}, {Top}), 大小: {Width}x{Height}";
        }
    }
}
